#pragma once
#include <string>
#include <chrono>
#include <functional>
#include <iostream>
#include <map>
#include <vector>

struct TestCase
{
	std::string result;
	std::string name;
	std::chrono::microseconds time;
	std::function<std::string()> function;

	TestCase(std::function<std::string()> function, std::string name)
	{
		this->function = function;
		this->name = name;
	}
	void run();
	void output();
	void compare(TestCase& o);
};

inline void TestCase::run()
{
	auto start = std::chrono::system_clock::now();
	result = function();
	auto end = std::chrono::system_clock::now();
	time = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
}

inline void TestCase::output()
{
	std::cout << "time: " << time.count() << std::endl;
	std::cout << "result:" << result << std::endl;
}
inline void TestCase::compare(TestCase& o)
{
	std::cout << "use time: " << time.count() << " " << o.time.count() << std::endl;
	std::cout << ((time.count() < o.time.count()) ? name : o.name) << " is better" << std::endl;
	if (result == o.result)
	{
		std::cout << "result is same" << std::endl;
		std::cout << "r:" << result << std::endl;
	}
	else
	{
		std::cout << "result not same....." << std::endl;
		std::cout << name << ":" << result << std::endl;
		std::cout << o.name << ":" << o.result << std::endl;
	}
}

extern std::map < std::string, std::vector<TestCase>> g_AllCases;

#define ADD_CASE(NAME,F) \
namespace STD { static char NAME = (g_AllCases[#NAME].push_back(TestCase(F, NS)), 0); }
